﻿using UnityEngine;
using System.Collections;

public class BGPlane2D:Plane2D, ILevelElementGUI
{
	protected float maxSize;
	Vector2 originalScale;
	
	float currenTileXScale;
	float previousTileXScale;
	
	Vector2 yScaleBounds;
	float previousYScale;
	float currentYScale;
	
	Vector2 xScaleBounds;
	float previousXScale;
	float currentXScale;
	
	float currentdt;
	float previousdt;
	
	public BGPlane2D(string planeName, Layer2D layer, Vector2 postion):base(planeName, layer)
	{
		gameObject.transform.position = new Vector3(postion.x, postion.y, layer.ZBuffer);
		originalScale = gameObject.transform.localScale;
		currenTileXScale = previousTileXScale = gameObject.renderer.material.mainTextureScale.x;
		currentdt = previousdt = 0.0f;
	}
	
	public BGPlane2D(string planeName, Layer2D layer, Vector2 postion, bool toDelete):base(planeName, layer, toDelete)
	{
		gameObject.transform.position = new Vector3(postion.x, postion.y, layer.ZBuffer);
		originalScale = gameObject.transform.localScale;
		currenTileXScale = previousTileXScale = gameObject.renderer.material.mainTextureScale.x;
		currentdt = previousdt = 0.0f;
	}
	
	private void XTile()
	{
		currenTileXScale = previousTileXScale;
		Vector2 offSet = gameObject.renderer.material.mainTextureScale;
		offSet.x = currenTileXScale;
		gameObject.renderer.material.mainTextureScale = offSet;
	}
	
	private void ScalePlane()
	{
		currentYScale = previousYScale;
		currentXScale = previousXScale;
		SetScale(new Vector2(currentXScale,  currentYScale));
	}

	private void MoveBG()
	{
		float change = (currentdt - previousdt) * 2.0f;
		currentdt = previousdt;
		Vector2 pastPosition = GetPosition();
		SetPosition(new Vector2(pastPosition.x, pastPosition.y + change));
	}
	
	public void ResetScaleAndPosition()
	{
		originalScale = GetScale();	
		currentYScale = previousYScale = originalScale.y;
		currentXScale = previousXScale = originalScale.x;
		yScaleBounds = new Vector2(currentYScale/10.0f, currentYScale * 10);
		xScaleBounds = new Vector2(currentXScale/10.0f, currentXScale * 10);
	}
			
	public bool ToShow ()
	{
		return (gameObject != null);
	}
	
	public void ShowGUIElements ()
	{
		GUILayout.Box(customName);
		GUILayout.BeginHorizontal();
		GUILayout.Box("Tile X: ", GUILayout.ExpandWidth(false));
		previousTileXScale = GUILayout.HorizontalSlider(previousTileXScale, 1, 5);
		
		if(previousTileXScale != currenTileXScale)
			XTile();
		GUILayout.EndHorizontal();
		
		GUILayout.BeginHorizontal();
		GUILayout.Box("Scale Y:", GUILayout.ExpandWidth(false));
		previousYScale = GUILayout.HorizontalSlider(previousYScale, yScaleBounds.x, yScaleBounds.y);
		if(previousYScale != currentYScale)
			ScalePlane();
		
		GUILayout.EndHorizontal();
		
		GUILayout.BeginHorizontal();
		GUILayout.Box("Scale X:", GUILayout.ExpandWidth(false));
		previousXScale = GUILayout.HorizontalSlider(previousXScale, xScaleBounds.x, xScaleBounds.y);
		if(previousXScale != currentXScale)
			ScalePlane();
		
		GUILayout.EndHorizontal();
		
		GUILayout.BeginHorizontal();
		GUILayout.Box("Offset Y:", GUILayout.ExpandWidth(false));
		previousdt = GUILayout.HorizontalSlider(previousdt, -4.5f, 4.5f);
		if(currentdt != previousdt)
			MoveBG();
		GUILayout.EndHorizontal();
		
		GUILayout.BeginHorizontal();
		if(canBeDeleted && GUILayout.Button("Delete"))
		{
			Destroy();
			Destroy(this);
		}
		GUILayout.EndHorizontal();
	}
}

public class Plane2D:Object
{
	static Shader defaultShader = Shader.Find("Custom/Unlit/Transparent");
	protected GameObject gameObject;
	protected string customName;
	
	Transform transform;
	
	protected Layer2D layer2D;
	protected bool canBeDeleted;
	XMLData.Map.Asset assetUsed;
	
	public Plane2D(string planeName, Layer2D layer)
	{
		gameObject = new GameObject(planeName);
		customName = planeName;
		layer2D = layer;
		transform = gameObject.transform;
		gameObject.layer = layer2D.MaskLayer;
		transform = gameObject.transform;
		transform.localScale = new Vector3(0.5f, 0.5f, 0.5f);
		
		Quaternion quaternion = gameObject.transform.localRotation;
		quaternion.eulerAngles = new Vector3(0, 180, 90);
		transform.localRotation = quaternion;

		gameObject.AddComponent<MeshRenderer>();
		Material bgmat = new Material(defaultShader);
		gameObject.GetComponent<MeshRenderer>().material = new Material(bgmat);
		
		gameObject.AddComponent<MeshFilter>();
		gameObject.GetComponent<MeshFilter>().mesh = NewMesh();
		canBeDeleted = false;
	}
	
	public Plane2D(string planeName, Layer2D layer, bool toDelete)
	{
		gameObject = new GameObject(planeName);
		customName = planeName;
		layer2D = layer;
		transform = gameObject.transform;
		gameObject.layer = layer2D.MaskLayer;
		transform = gameObject.transform;
		transform.localScale = new Vector3(0.5f, 0.5f, 0.5f);
		
		Quaternion quaternion = gameObject.transform.localRotation;
		quaternion.eulerAngles = new Vector3(0, 180, 90);
		transform.localRotation = quaternion;

		gameObject.AddComponent<MeshRenderer>();
		Material bgmat = new Material(defaultShader);
		gameObject.GetComponent<MeshRenderer>().material = new Material(bgmat);
		
		gameObject.AddComponent<MeshFilter>();
		gameObject.GetComponent<MeshFilter>().mesh = NewMesh();
		canBeDeleted = toDelete;
	}
	
	public void Load(XMLData.Map.Plane2DInfo info)
	{
		SetPosition(new Vector2(info.position.x, info.position.y));
		SetMaterial(info.planeMaterial);
		SetScale(new Vector2(info.scale.x, info.scale.y));
		customName = info.planeName;
	}
	
	public T AddComponent<T>() where T: Component
	{
		return gameObject.AddComponent<T>();
	}
	
	public void RemoveComponent<T>() where T: Component
	{
		Destroy(gameObject.GetComponent<T>());
	}
	
	public void SetPosition(Vector2 position)
	{
		transform.position = new Vector3(position.x, position.y, layer2D.ZBuffer);
	}
	
	public Vector2 GetPosition()
	{
		Vector3 _position = transform.position;
		return new Vector2(_position.x, _position.y);
	}
	
	public void Translate(Vector2 dt)
	{
		Vector2 position = GetPosition();
		position.x += dt.x;
		position.y += dt.y;
		SetPosition(position);
	}
	
	public void SetScale(Vector2 newScale)
	{
		transform.localScale = new Vector3(0.5f *newScale.y , 0.5f * newScale.x, 0.5f);
	}
	
	public Vector2 GetScale()
	{
		Vector3 _scale = transform.localScale;
		return new Vector2(_scale.y/0.5f , _scale.x/0.5f);	
	}
	public void SetColor(Color color)
	{
		gameObject.renderer.material.color = color;
	}
	
	public Color GetColor()
	{
		return gameObject.renderer.material.color;
	}
	
	public string Name
	{
		get{return gameObject.name;}
	}
	
	public void Rotate(float angle)
	{
		
	}
	
	public void SetImage(KEYTYPE assetType, Texture2D image)
	{
		assetUsed = new XMLData.Map.Asset();
		assetUsed.assetType = (int)assetType;
		assetUsed.name = image.name;
		gameObject.renderer.material.mainTexture = image;
	}
	
	public Texture Image
	{
		get{return gameObject.renderer.material.mainTexture;}
	}
	
	public Layer2D AttachedLayer
	{
		get{return layer2D;}
	}
	
	public void Destroy()
	{
		layer2D.RemovePlane2D(this);
		Object.Destroy(gameObject);
	}
	
	public void SetMaterial(XMLData.UnityObject.XMLMaterial material)
	{
		XMLData.UnityObject.XMLVector2 offSet = material.offSet;
		XMLData.UnityObject.XMLVector2 scale = material.scale;
		gameObject.renderer.material.mainTextureOffset = new Vector2(offSet.x, offSet.y);
		gameObject.renderer.material.mainTextureScale = new Vector2(scale.x, scale.y);
		gameObject.renderer.material.mainTexture = LevelAssetManager.Instance.getAsset<Texture2D>((KEYTYPE)material.mainTexture.assetType, 
														material.mainTexture.name);
		assetUsed = material.mainTexture;
	}
	
	public XMLData.Map.Plane2DInfo Package()
	{
		XMLData.Map.Plane2DInfo plane2d = new XMLData.Map.Plane2DInfo();
		
		//Create material 
		XMLData.UnityObject.XMLMaterial material =  plane2d.planeMaterial = new XMLData.UnityObject.XMLMaterial();
		
		//Create asset data of material
		XMLData.Map.Asset asset = material.mainTexture = new XMLData.Map.Asset();
		
		//Set the off set value of material
		material.offSet  = new XMLData.UnityObject.XMLVector2();
		material.offSet.SetValue(gameObject.renderer.material.mainTextureOffset);
		
		//Set the scale value of material
		material.scale = new XMLData.UnityObject.XMLVector2();
		material.scale.SetValue(gameObject.renderer.material.mainTextureScale);
		
		//Set the type of Image used
		asset.assetType = (int)assetUsed.assetType;
		asset.name = assetUsed.name;
		
		plane2d.Layer2DIndex = layer2D.LayerIndex; //Not really useful
		plane2d.planeName = gameObject.name;
		
		//Set the position of the plane
		plane2d.position = new XMLData.UnityObject.XMLVector2();
		plane2d.position.SetValue(GetPosition());
		
		//Set the plane scale
		plane2d.scale = new XMLData.UnityObject.XMLVector2();
		plane2d.scale.SetValue(GetScale());
		return plane2d; 
	}
	
	static Mesh NewMesh()
	{
		float size = 1;
		Mesh m = new Mesh();
	    m.name = "2dmesh";
		m.vertices = new Vector3[] {new Vector3(-size, -size, 0.01f),new Vector3(size, -size, 0.01f),new Vector3(size, size, 0.01f),new Vector3(-size, size, 0.01f)};
	    m.uv = new Vector2[] {new Vector2 (0, 0),new Vector2 (0, 1),new Vector2(1, 1),new Vector2 (1, 0)};
		m.triangles = new int[] {0, 1, 2, 0, 2, 3};
	    m.RecalculateNormals();
		return m;
	}
	
	
}
